home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 366_01 / ue311c1.arc / DISPLAY.C < prev    next >
C/C++ Source or Header  |  1991-10-25  |  37KB  |  1,675 lines

  1. /*
  2.  * The functions in this file handle redisplay. There are two halves, the
  3.  * ones that update the virtual display screen, and the ones that make the
  4.  * physical display screen the same as the virtual display screen. These
  5.  * functions use hints that are left in the windows by the commands.
  6.  *
  7.  */
  8.  
  9. #include    <stdio.h>
  10. #include    "estruct.h"
  11. #include    "eproto.h"
  12. #include    "edef.h"
  13. #include    "elang.h"
  14.  
  15. typedef struct    VIDEO {
  16.     int    v_flag;         /* Flags */
  17. #if    COLOR
  18.     int    v_fcolor;        /* current forground color */
  19.     int    v_bcolor;        /* current background color */
  20.     int    v_rfcolor;        /* requested forground color */
  21.     int    v_rbcolor;        /* requested background color */
  22. #endif
  23. #if    INSDEL && MEMMAP == 0
  24.     int    v_rline;        /* requested screen line # */
  25. #endif
  26.     char    v_text[1];        /* Screen data. */
  27. }    VIDEO;
  28.  
  29. #define VFCHG    0x0001            /* Changed flag         */
  30. #define VFEXT    0x0002            /* extended (beyond column 80)    */
  31. #define VFREV    0x0004            /* reverse video status     */
  32. #define VFREQ    0x0008            /* reverse video request    */
  33. #define VFCOL    0x0010            /* color change requested    */
  34.  
  35. static VIDEO   **vscreen;               /* Virtual screen. */
  36. #if    MEMMAP == 0
  37. static VIDEO   **pscreen;               /* Physical screen. */
  38. #endif
  39.  
  40. /*    some local function declarations    */
  41.  
  42. #if    PROTO
  43. #if    MEMMAP
  44. extern PASCAL NEAR updateline(int row, struct VIDEO *vp1);
  45. #else
  46. extern PASCAL NEAR updateline(int row, struct VIDEO *vp1, struct VIDEO *vp2);
  47. #endif
  48. #else
  49. extern PASCAL NEAR updateline();
  50. #endif
  51.  
  52. /*
  53.  * Initialize the data structures used by the display code. The edge vectors
  54.  * used to access the screens are set up. The operating system's terminal I/O
  55.  * channel is set up. All the other things get initialized at compile time.
  56.  * The original window has "WFCHG" set, so that it will get completely
  57.  * redrawn on the first call to "update".
  58.  */
  59.  
  60. PASCAL NEAR vtinit()
  61. {
  62.     register int i;
  63.     register VIDEO *vp;
  64.  
  65.     TTopen();        /* open the screen */
  66.     TTkopen();        /* open the keyboard */
  67.     TTrev(FALSE);
  68.  
  69.  
  70.     /* allocate the virtual screen pointer array */
  71.     vscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *));
  72.     if (vscreen == NULL)
  73.         meexit(1);
  74.  
  75. #if    MEMMAP == 0
  76.     /* allocate the physical shadow screen array */
  77.     pscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *));
  78.     if (pscreen == NULL)
  79.         meexit(1);
  80. #endif
  81.  
  82.     /* for every line in the display */
  83.     for (i = 0; i < term.t_mrow; ++i) {
  84.  
  85.         /* allocate a virtual screen line */
  86.         vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol);
  87.         if (vp == NULL)
  88.             meexit(1);
  89.  
  90.         vp->v_flag = 0;        /* init change clags */
  91. #if    COLOR
  92.         vp->v_rfcolor = 7;    /* init fore/background colors */
  93.         vp->v_rbcolor = 0;
  94. #endif
  95.         /* connect virtual line to line array */
  96.         vscreen[i] = vp;
  97.  
  98. #if    MEMMAP == 0
  99.         /* allocate and initialize physical shadow screen line */
  100.         vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol);
  101.         if (vp == NULL)
  102.             meexit(1);
  103.  
  104.         vp->v_flag = 0;
  105. #if    INSDEL
  106.         vp->v_rline = i;    /* set requested line position */
  107. #endif
  108.         pscreen[i] = vp;
  109. #endif
  110.     }
  111. }
  112.  
  113. #if    CLEAN
  114. /* free up all the dynamically allocated video structures */
  115.  
  116. PASCAL NEAR vtfree()
  117. {
  118.     int i;
  119.     for (i = 0; i < term.t_mrow; ++i) {
  120.         free(vscreen[i]);
  121. #if    MEMMAP == 0
  122.         free(pscreen[i]);
  123. #endif
  124.     }
  125.     free(vscreen);
  126. #if    MEMMAP == 0
  127.     free(pscreen);
  128. #endif
  129. }
  130. #endif
  131.  
  132. /*
  133.  * Clean up the virtual terminal system, in anticipation for a return to the
  134.  * operating system. Move down to the last line and clear it out (the next
  135.  * system prompt will be written in the line). Shut down the channel to the
  136.  * terminal.
  137.  */
  138. PASCAL NEAR vttidy()
  139. {
  140.     mlerase();
  141.     movecursor(term.t_nrow, 0);
  142.     TTflush();
  143.     TTclose();
  144.     TTkclose();
  145. }
  146.  
  147. /*
  148.  * Set the virtual cursor to the specified row and column on the virtual
  149.  * screen. There is no checking for nonsense values; this might be a good
  150.  * idea during the early stages.
  151.  */
  152. PASCAL NEAR vtmove(row, col)
  153.  
  154. int row, col;
  155.  
  156. {
  157.     vtrow = row;
  158.     vtcol = col;
  159. }
  160.  
  161. /* Write a character to the virtual screen. The virtual row and
  162.    column are updated. If we are not yet on left edge, don't print
  163.    it yet. If the line is too long put a "$" in the last column.
  164.    This routine only puts printing characters into the virtual
  165.    terminal buffers. Only column overflow is checked.
  166. */
  167.  
  168. PASCAL NEAR vtputc(c)
  169.  
  170. int c;
  171.  
  172. {
  173.     register VIDEO *vp;    /* ptr to line being updated */
  174.  
  175.     vp = vscreen[vtrow];
  176.  
  177.     if (c == '\t') {
  178.         do {
  179.             vtputc(' ');
  180.         } while (((vtcol + taboff) % (tabsize)) != 0);
  181.     } else if (vtcol >= term.t_ncol) {
  182.         ++vtcol;
  183.         vp->v_text[term.t_ncol - 1] = '$';
  184.     } else if (disphigh && c > 0x7f) {
  185.         vtputc('^');
  186.         vtputc('!');
  187.         c -= 0x80;
  188.         if (c == '\t') {
  189.             vtputc('^');
  190.             vtputc('I');
  191.         } else
  192.             vtputc(c);
  193.     } else if (c < 0x20 || c == 0x7F) {
  194.         vtputc('^');
  195.         vtputc(c ^ 0x40);
  196.     } else {
  197.         if (vtcol >= 0)
  198.             vp->v_text[vtcol] = c;
  199.         ++vtcol;
  200.     }
  201. }
  202.  
  203. /*
  204.  * Erase from the end of the software cursor to the end of the line on which
  205.  * the software cursor is located.
  206.  */
  207. PASCAL NEAR vteeol()
  208. {
  209.     register VIDEO    *vp;
  210.  
  211.     vp = vscreen[vtrow];
  212.     while (vtcol < term.t_ncol) {
  213.         if (vtcol >= 0)
  214.         vp->v_text[vtcol] = ' ';
  215.     vtcol++;
  216.     }
  217. }
  218.  
  219. /* upscreen:    user routine to force a screen update
  220.         always finishes complete update     */
  221.  
  222. PASCAL NEAR upscreen(f, n)
  223.  
  224. int f,n;    /* prefix flag and argument */
  225.  
  226. {
  227.     update(TRUE);
  228.     return(TRUE);
  229. }
  230.  
  231. /*
  232.  * Make sure that the display is right. This is a three part process. First,
  233.  * scan through all of the windows looking for dirty ones. Check the framing,
  234.  * and refresh the screen. Second, make sure that "currow" and "curcol" are
  235.  * correct for the current window. Third, make the virtual and physical
  236.  * screens the same.
  237.  */
  238. PASCAL NEAR update(force)
  239.  
  240. int force;    /* force update past type ahead? */
  241.  
  242. {
  243.     register WINDOW *wp;
  244.  
  245. #if    TYPEAH
  246.     if (force == FALSE && typahead())
  247.         return(TRUE);
  248. #endif
  249. #if    VISMAC == 0
  250.     if (force == FALSE && kbdmode == PLAY)
  251.         return(TRUE);
  252. #endif
  253.  
  254.     /* update any windows that need refreshing */
  255.     wp = wheadp;
  256.     while (wp != NULL) {
  257.         if (wp->w_flag) {
  258.             /* if the window has changed, service it */
  259.             reframe(wp);    /* check the framing */
  260.             if ((wp->w_flag & ~WFMODE) == WFEDIT)
  261.                 updone(wp);    /* update EDITed line */
  262.             else if (wp->w_flag & ~WFMOVE)
  263.                 updall(wp);    /* update all lines */
  264.             if (wp->w_flag & WFMODE)
  265.                 modeline(wp);    /* update modeline */
  266.             wp->w_flag = 0;
  267.             wp->w_force = 0;
  268.         }
  269.  
  270. #if    1    /* take this out before the release! */
  271.     if (wp->w_wndp == wheadp) {    /* erroneously circular list */
  272.         wp->w_wndp = (WINDOW *)NULL;
  273.         mlwrite("DAN!!! a bogus circular window list!!!");
  274.         TTgetc();
  275.     }
  276. #endif
  277.         /* on to the next window */
  278.         wp = wp->w_wndp;
  279.     }
  280.  
  281.     /* recalc the current hardware cursor location */
  282.     updpos();
  283.  
  284. #if    MEMMAP
  285.     /* update the cursor and flush the buffers */
  286.     movecursor(currow, curcol - lbound);
  287. #endif
  288.  
  289.     /* check for lines to de-extend */
  290.     upddex();
  291.  
  292.     /* if screen is garbage, re-plot it */
  293.     if (sgarbf != FALSE)
  294.         if (gflags & GFSDRAW)
  295.             sgarbf = FALSE;
  296.         else
  297.             updgar();
  298.  
  299.     /* update the virtual screen to the physical screen */
  300.     updupd(force);
  301.  
  302.     /* update the cursor and flush the buffers */
  303.     movecursor(currow, curcol - lbound);
  304.     TTflush();
  305.  
  306.     return(TRUE);
  307. }
  308.  
  309. /*    reframe:    check to see if the cursor is on in the window
  310.             and re-frame it if needed or wanted        */
  311.  
  312. PASCAL NEAR reframe(wp)
  313.  
  314. WINDOW *wp;
  315.  
  316. {
  317.     register LINE *lp;    /* search pointer */
  318.     register LINE *rp;    /* reverse search pointer */
  319.     register LINE *hp;    /* ptr to header line in buffer */
  320.     register LINE *tp;    /* temp debugging pointer */
  321.     register int i;        /* general index/# lines to scroll */
  322.     register int nlines;    /* number of lines in current window */
  323.  
  324.     /* figure out our window size */
  325.     nlines = wp->w_ntrows;
  326.     if (modeflag == FALSE)
  327.         nlines++;
  328.  
  329.     /* if not a requested reframe, check for a needed one */
  330.     if ((wp->w_flag & WFFORCE) == 0) {
  331.         lp = wp->w_linep;
  332.         for (i = 0; i < nlines; i++) {
  333.  
  334.             /* if the line is in the window, no reframe */
  335.             if (lp == wp->w_dotp)
  336.                 return(TRUE);
  337.  
  338.             /* if